package com.nineclock.system.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.sms.AliyunSmsUtils;
import com.nineclock.common.utils.PhoneNumCheckUtils;
import com.nineclock.system.dto.SysUserDTO;
import com.nineclock.system.service.SmsService;
import com.nineclock.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.Duration;

@Service
@Slf4j
@Transactional
public class SmsServiceImpl implements SmsService {


    @Autowired
    private AliyunSmsUtils smsUtils;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private SysUserService userService;
    /**
     * 短信: 发送短信验证码
     * @param mobile 手机号
     * @param type 操作类型
     */
    @Override
    public void sendSms(String mobile, String type) {
        // 1.参数校验
        // 1.1 参数不能为空
        if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(type)){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        // 1.2 手机号码格式校验
        if (!PhoneNumCheckUtils.isPhoneLegal(mobile)){
            throw new NcException(ResponseEnum.INVALID_PHONE_NUMBER);
        }
        SysUserDTO user = userService.queryUser(mobile);
        // 1.3 如果是注册，还需要判断手机号码有没有被注册过
        if (type.equals(SMSConstant.SMS_TYPE_REGISTER)){
            if (user !=null){
                throw new NcException(ResponseEnum.USER_MOBILE_EXISTS);
            }
        }else {
            // 1.4 如果是其他业务，手机号必须存在
            if (user==null){
                throw new NcException(ResponseEnum.USER_NOT_REGISTER);
            }
        }
        // 2.生成六位随机数验证码
        String code = RandomUtil.randomNumbers(6);
        // 3.调用阿里云短信，发送验证码
        //Boolean sendSMSResult = smsUtils.sendSMS(mobile, code);
        //if (!sendSMSResult){
        //    throw new NcException(ResponseEnum.SEND_MESSAGE_ERROR);
        //}
        // 4.存储验证码到redis，并设置过期时间，key必须唯一
        // 4.1 根据业务类型，获取前缀
        String prefix=getPrefix(type);
        redisTemplate.opsForValue().set(prefix+mobile,code, Duration.ofMinutes(5));
        log.info("短信发送成功，手机号 = " + mobile + "，业务类型 = " + type + "，验证码 = " + code);
    }


    /**
     * 短信: 验证码校验
     *
     * @param mobile
     * @param checkcode
     * @param type
     * @return
     */
    @Override
    public Boolean verifySmsCode(String mobile, String checkcode, String type) {
        if (StringUtils.isEmpty(mobile)||StringUtils.isEmpty(checkcode)||StringUtils.isEmpty(type)){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //获取业务类型
        String prefix = getPrefix(type);
        //获取验证码
        String redisCode = redisTemplate.opsForValue().get(prefix + mobile);
        //验证码校验
        if (!StringUtils.isEmpty(checkcode)&&redisCode.equals(checkcode)){
            redisTemplate.delete(prefix+mobile);
            return true;
        }
        return false;
    }

    /**
     * 根据操作类型，获取验证码前缀
     * @param type
     * @return
     */
    private String getPrefix(String type){
        String prefix = "";
        switch (type){
            case "1":
                prefix = SMSConstant.SMS_LOGIN_KEY_PREFIX;//登录
                break;
            case "2":
                prefix = SMSConstant.SMS_REGISTER_KEY_PREFIX;//注册
                break;
            case "3":
                prefix = SMSConstant.SMS_CHANGE_MANAGER_KEY_PREFIX;//更改管理员
                break;
            case "4":
                prefix = SMSConstant.SMS_RESET_KEY_PREFIX;//重置密码
                break;
            default:
                break;
        }
        return prefix;
    }
}
